/***********************************************************************
* Kenny Davidson - Project3 - PrintVisitor.h
*
* Defines PrintVisitor Operations
***********************************************************************/
#include "PrintVisitor.h"
#include <iostream>
#include <cassert>

#include "Char.h"
#include "Command.h"
#include "Id.h"
#include "Index.h"
#include "Number.h"
#include "StatementList.h"
#include "String.h"

#include "Add.h"
#include "Sub.h"
#include "Mul.h"
#include "Div.h"
#include "Mod.h"
#include "Neg.h"
#include "Equ.h"

#include "DoubleEqual.h"
#include "NotEqual.h"
#include "Less.h"
#include "LessEqual.h"
#include "Greater.h"
#include "GreaterEqual.h"
#include "And.h"
#include "Or.h"

#include "While.h"
#include "If.h"

using namespace std;


void PrintVisitor::visitNumber( Number* NUM )
{ cout << NUM->getValue(); }

void PrintVisitor::visitIndex( Index* INDEX )
{
}

void PrintVisitor::visitChar( Char* CHAR )
{
}

void PrintVisitor::visitString( String* STRING )
{
}

void PrintVisitor::visitId( Id* ID )
{ cout << ID->getName(); }

void PrintVisitor::visitStatementList( StatementList* SL )
{
	cout << "{" << endl;
	for( list<Node*>::const_iterator it = SL->getStatementList().begin(); it != SL->getStatementList().end(); it++ )
	{
		(*it)->accept(*this);
		cout << ";" << endl;
	}
	cout << "}" << endl;
}

void PrintVisitor::visitCommand( Command* COMMAND )
{
	cout << COMMAND->getName() << "(";
	bool firsttime = true;
	for( list<Node*>::const_iterator it = COMMAND->getExprList().begin(); it != COMMAND->getExprList().end(); it++ )
	{
		if( !firsttime ) cout << ", ";
		firsttime = false;
		(*it)->accept(*this);
	}
	cout << ")";
}

void PrintVisitor::visitAdd( Add* ADD )
{
	cout << "(";
	ADD->getLeft()->accept(*this);
	cout << " + ";
	ADD->getRight()->accept(*this);
	cout << ")";
}

void PrintVisitor::visitSub( Sub* SUB )
{
	cout << "(";
	SUB->getLeft()->accept(*this);
	cout << " - ";
	SUB->getRight()->accept(*this);
	cout << ")";
}

void PrintVisitor::visitMul( Mul* MUL )
{
	cout << "(";
	MUL->getLeft()->accept(*this);
	cout << " * ";
	MUL->getRight()->accept(*this);
	cout << ")";
}

void PrintVisitor::visitDiv( Div* DIV )
{
	cout << "(";
	DIV->getLeft()->accept(*this);
	cout << " / ";
	DIV->getRight()->accept(*this);
	cout << ")";
}

void PrintVisitor::visitMod( Mod* MOD )
{
	cout << "(";
	MOD->getLeft()->accept(*this);
	cout << " % ";
	MOD->getRight()->accept(*this);
	cout << ")";
}

void PrintVisitor::visitEqu( Equ* EQU )
{
	EQU->getLeft()->accept(*this);
	cout << " = ";
	EQU->getRight()->accept(*this);
}

void PrintVisitor::visitNeg( Neg* NEG )
{
	cout << "-";
	NEG->getChild()->accept(*this);
}

void PrintVisitor::visitAnd( And* AND )
{
}

void PrintVisitor::visitOr( Or* OR )
{
}

void PrintVisitor::visitLess( Less* LESS )
{
}

void PrintVisitor::visitLessEqual( LessEqual* LESSEQUAL )
{
}

void PrintVisitor::visitGreater( Greater*  GREATER )
{
}

void PrintVisitor::visitGreaterEqual( GreaterEqual* GREATEREQUAL )
{
}

void PrintVisitor::visitDoubleEqual( DoubleEqual* DOUBLEEQUAL )
{
}

void PrintVisitor::visitNotEqual( NotEqual* NOTEQUAL )
{
}

void PrintVisitor::visitWhile( While* WHILE )
{
	cout << "while( ";
	WHILE->getCondition()->accept(*this);
	cout << " )" << endl;
	WHILE->getBlock()->accept(*this);
}

void PrintVisitor::visitIf( If* IF )
{
	const vector<Node*> blocks = IF->getBlocks();
	cout << "if( ";
	IF->getCondition()->accept(*this);
	cout << " )" << endl;
	assert( blocks.size() != 0 );
	(*blocks.begin())->accept(*this);
	if( blocks.size() > 1 )
	{
		cout << "else" << endl;
		(*(blocks.end()-1))->accept(*this);
	}
	cout << "XXXXXX" << endl;
}

